package com.heima.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.heima.article.client.ArticleFeign;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.threadlocal.UserThreadLocalUtils;
import com.heima.common.util.JsonUtils;
import com.heima.common.util.JwtUtils;
import com.heima.model.article.dtos.AuthorDto;
import com.heima.model.behavior.dtos.FollowBehaviorDto;
import com.heima.model.user.dtos.AppLoginDto;
import com.heima.model.user.dtos.UserRelationDto;
import com.heima.user.entity.ApUser;
import com.heima.user.entity.ApUserFan;
import com.heima.user.entity.ApUserFollow;
import com.heima.user.mapper.ApUserMapper;
import com.heima.user.service.IApUserFanService;
import com.heima.user.service.IApUserFollowService;
import com.heima.user.service.IApUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.heima.common.constants.message.FollowBehaviorConstants.FOLLOW_BEHAVIOR_TOPIC;

/**
 * <p>
 * APP用户信息表 服务实现类
 * </p>
 *
 * @author heima
 * @since 2021-03-13
 */
@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements IApUserService {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public Map<String, Object> login(AppLoginDto dto) {
        if(StringUtils.isBlank(dto.getPhone()) && StringUtils.isBlank(dto.getPassword()) && StringUtils.isBlank(dto.getEquipmentId())){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID);
        }
        Map<String,Object> map = new HashMap<>();

        Integer userId=0;
        //1、判断是否传递了手机号和密码
        if(StringUtils.isNotBlank(dto.getPhone()) && StringUtils.isNotBlank(dto.getPassword())){
            //2、基于手机号查询用户信息
            QueryWrapper<ApUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ApUser::getPhone,dto.getPhone());
            ApUser apUser = this.getOne(queryWrapper);
            if(apUser==null){
                throw new LeadException(AppHttpCodeEnum.PARAM_INVALID,"用户手机号错误");
            }
            //3、判断密码是否正确
            boolean matches = passwordEncoder.matches(dto.getPassword(), apUser.getPassword());
            if(!matches){
                throw new LeadException(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
            }
            userId=apUser.getId();
            apUser.setPassword("");
            map.put("user",apUser);
        }else{
            //4、如果是设备等，将0作为用户id存入token中
            if(StringUtils.isBlank(dto.getEquipmentId())){
                throw new LeadException(AppHttpCodeEnum.PARAM_INVALID,"设备号不存在");
            }
        }

        //5、生成token，并将用户信息和token存入map集合
        String token = JwtUtils.generateTokenExpireInSeconds(userId, 3600);
        map.put("token",token);
        return map;
    }

    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private IApUserFollowService followService;

    @Autowired
    private IApUserFanService fanService;

    @Override
    public void userFollow(UserRelationDto dto) {
        if(dto==null || dto.getOperation()<0 || dto.getOperation()>1){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID);
        }

        //1、根据作者id，远程调用article微服务查询作者信息
        Integer authorId = dto.getAuthorId();
        if(authorId ==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_INVALID,"作者id参数异常");
        }
        AuthorDto authorDto = articleFeign.getAuthorById(authorId);
        //2、获取作者对应的app用户id值  followId
        if(authorDto==null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"作者信息不存在");
        }
        //获取作者关联的App用户id信息
        Integer followId = authorDto.getUserId();
        //获取当前登录用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if(userId==null || userId==0){
            //需要登录
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //3、判断operation是关注还是取消关注
        if(dto.getOperation()==1){
            //3.1、如果是关注行为，记录关注表和粉丝表数据
            followUser(userId,followId,dto.getArticleId());
        }else{
            //3.1、如果是取消关注行为，删除关注表和粉丝表数据
            cancelFollowUser(userId,followId);
        }

    }

    @Override
    public Boolean findByUserIdAndFollowId(Integer userId, Integer followId) {
        //构建查询条件
        QueryWrapper<ApUserFollow> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ApUserFollow::getUserId,userId).eq(ApUserFollow::getFollowId,followId);
        int count = followService.count(queryWrapper);
        if(count>0){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 取消关注行为，删除关注表和粉丝表数据
     * @param userId
     * @param followId
     */
    @Transactional
    public void cancelFollowUser(Integer userId, Integer followId) {
        QueryWrapper<ApUserFollow> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ApUserFollow::getFollowId,followId).eq(ApUserFollow::getUserId,userId);
        //删除关注表数据
        boolean b = followService.remove(queryWrapper);
        if(!b){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"删除关注数据失败");
        }

        QueryWrapper<ApUserFan> fanQueryWrapper = new QueryWrapper<>();
        fanQueryWrapper.lambda().eq(ApUserFan::getFansId,userId).eq(ApUserFan::getUserId,followId);
        //删除粉丝数据
        boolean b1 = fanService.remove(fanQueryWrapper);
        if(!b1){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"删除粉丝数据失败");
        }

    }

    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
     * 关注行为，记录关注表和粉丝表数据
     * @param userId
     * @param followId
     * @param articleId
     */
    @Transactional
    public void followUser(Integer userId, Integer followId, Long articleId) {
        //查询关注的作者是否存在
        ApUser apUser = this.getById(followId);
        if(apUser==null){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"关注的作者不存在");
        }

        //查询当前用户是否关注了该作者
        QueryWrapper<ApUserFollow> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ApUserFollow::getFollowId,followId).eq(ApUserFollow::getUserId,userId);
        int count = followService.count(queryWrapper);
        if(count>0){
            throw new LeadException(AppHttpCodeEnum.DATA_EXIST,"已关注该作者");
        }
        //记录关注操作
        ApUserFollow userFollow = new ApUserFollow();
        userFollow.setUserId(userId);
        userFollow.setFollowId(followId);
        userFollow.setFollowName(apUser.getName());
        userFollow.setLevel(0);
        userFollow.setIsNotice(true);
        userFollow.setCreatedTime(new Date());
        boolean b = followService.save(userFollow);
        if(!b){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"保存关注数据失败");
        }
        //查询粉丝记录是否存在
        //查询粉丝信息
        ApUser fanUser = this.getById(userId);
        QueryWrapper<ApUserFan> fanQueryWrapper = new QueryWrapper<>();
        fanQueryWrapper.lambda().eq(ApUserFan::getFansId,userId).eq(ApUserFan::getUserId,followId);
        int count1 = fanService.count(fanQueryWrapper);
        if(count1==0){
            //记录粉丝数据
            ApUserFan userFan = new ApUserFan();
            userFan.setUserId(followId);
            userFan.setFansId(userId);
            userFan.setFansName(fanUser.getName());
            userFan.setLevel(0);
            userFan.setCreatedTime(new Date());
            userFan.setIsDisplay(true);
            userFan.setIsShieldComment(false);
            userFan.setIsShieldLetter(false);
            boolean b1 = fanService.save(userFan);
            if(!b1){
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"保存粉丝数据失败");
            }
        }

        //生成消息，记录关注行为操作
        FollowBehaviorDto dto = new FollowBehaviorDto();
        dto.setUserId(userId);
        dto.setFollowId(followId);
        dto.setArticleId(articleId);
        kafkaTemplate.send(FOLLOW_BEHAVIOR_TOPIC, JsonUtils.toString(dto));

    }
}
